#include "lib/helpers/pvmoutstreamhelpers.h"
#include "lib/pvmsystem.h"
#include "lib/pvmstrings.h"

#include "lib/memory/pvmmemory.h"

PVMAPI IPvmOutStream* PVMCALL PVMHCreateFileOutputStream(const pvm_char* fileName, pvm_bool truncateFile)
{
	return PVMHFileOutputStream::CreateW(fileName, truncateFile);
}

PVMHFileOutputStream::PVMHFileOutputStream()
{
	name = NULL;
	file = PVM_EMPTY_FILE_HANDLE;
}

PVMHFileOutputStream::~PVMHFileOutputStream()
{
	if(name)
		PVMMemoryFree(name);

	if(file!=PVM_EMPTY_FILE_HANDLE)
		PVMFileClose(file);

	name = NULL;
	file = PVM_EMPTY_FILE_HANDLE;
}

IPvmOutStream* PVMHFileOutputStream::CreateW(const pvm_char* fileName, pvm_bool truncateFile)
{
	PVMHFileOutputStream* stream = new PVMHFileOutputStream();
	if(!stream)
		return NULL;

	pvm_int32 mode = PVM_WRITE;
	if(truncateFile)
		mode |= PVM_CREATE_ALWAYS;
	else
		mode |= PVM_OPEN_ALWAYS;

	PVMFileHandle f = PVMFileOpen(fileName, mode);
	if(f==PVM_FILE_OPEN_ERROR)
	{
		delete( stream);
		return NULL;
	}

	stream->file = f;

	pvm_size strLen = pvm_strlen(fileName);
	pvm_char *newStr = (pvm_char*)PVMMemoryAlloc((strLen+1) * sizeof(pvm_char));
	if(newStr)
	{
		pvm_strcpy(newStr, fileName);
		stream->name = newStr;
	}

	return stream;
}

pvm_size PVMHFileOutputStream::Write(void *buf, pvm_size size)
{
	pvm_size result = 0;
	PVMFileWrite(file, buf, size, &result);
	return result;
}

pvm_bool PVMHFileOutputStream::Seek(pvm_file_size pos, TPvmSeek origin)
{
	return PVMFileSeek(file, pos, origin);
}

pvm_file_size PVMHFileOutputStream::Tell()
{
	return PVMFileTell(file);
}

void PVMHFileOutputStream::Close()
{
	delete( this);
}

pvm_file_size PVMHFileOutputStream::Size()
{
	return PVMFileSize(file);
}

pvm_bool PVMHFileOutputStream::Seekable()
{
	return true;
}

//*************************************************************

PVMOutCallbacksStream::PVMOutCallbacksStream(IPVMWriteCallbacks* callbacks, void *src)
{
	this->callbacks = callbacks;
	this->src = src;
}

PVMOutCallbacksStream::~PVMOutCallbacksStream()
{
	callbacks = NULL;
	src = NULL;
}

pvm_size PVMOutCallbacksStream::Write(void *buf, pvm_size size)
{
	return callbacks->Write(src, buf, size);
}

pvm_bool PVMOutCallbacksStream::Seek(pvm_file_size pos, TPvmSeek origin)
{
	return callbacks->Seek(src, pos, origin);
}

pvm_file_size PVMOutCallbacksStream::Tell()
{
	return callbacks->Tell(src);
}

void PVMOutCallbacksStream::Close()
{
	return callbacks->Close(src);
}

pvm_file_size PVMOutCallbacksStream::Size()
{
	return callbacks->Size(src);
}

pvm_bool PVMOutCallbacksStream::Seekable()
{
	return callbacks->Seekable(src);
}
